#ifndef LOGMGR_H
#define LOGMGR_H

#include "manager.h"
#include "logger.h"
#include <map>

inline wxString F( const wxChar* msg, ... ) {
  va_list arg_list;
  va_start( arg_list, msg );
  ::temp_string = wxString::FormatV( msg, arg_list );
  va_end( arg_list );
  return ::temp_string;
}

struct LogSlot {
  friend class LogManager;
  Logger* log;
  size_t index;
  wxBitmap* icon;
  wxString title;
  LogSlot();
  ~LogSlot();
  size_t Index() const;
  void SetLogger( Logger* in );
  Logger* GetLogger() const;
};

class LogManager : public Mgr<LogManager> {
  public:
    struct InstantiatorBase {
      virtual Logger* New() { return nullptr; };
      virtual bool RequiresFilename() const { return false; };
      virtual ~InstantiatorBase() { ; };
    };
    template<typename type, bool requires_filename = false> struct Instantiator : public InstantiatorBase {
      virtual Logger* New() { return new type; };
      virtual bool RequiresFilename() const { return requires_filename; };
    };

    enum { max_logs = 32 };
  private:
    typedef std::map<wxString, InstantiatorBase*> inst_map_t;
    inst_map_t instMap;
    LogSlot slot[max_logs + 1];
    LogManager();
    ~LogManager();
    friend class Mgr<LogManager>;
    friend class Manager;
    void ClearLogInternal( int i );
    void LogInternal( const wxString& msg, int i, Logger::level lv );
  public:
    enum { no_index = -1, invalid_log, stdout_log, app_log, debug_log};
    size_t SetLog( Logger* l, int index = no_index );
    void DeleteLog( int i );
    LogSlot& Slot( int i );
    size_t FindIndex( Logger* l );
    void Log( const wxString& msg, int i = app_log, Logger::level lv = Logger::info ) { LogInternal( msg, i, lv ); };
    void LogWarning( const wxString& msg, int i = app_log ) { Log( msg, i, Logger::warning ); };
    void LogError( const wxString& msg, int i = app_log ) { Log( msg, i, Logger::error ); };
    void Panic( const wxString& msg, const wxString& component = wxEmptyString );
    void DebugLog( const wxString& msg, Logger::level lv = Logger::info ) { Log( msg, debug_log, lv ); };
    void DebugLogError( const wxString& msg ) { DebugLog( msg, Logger::error ); };
    void LogInf( const wxString& msg, Logger::level lv = Logger::info ) { Log( msg, stdout_log, lv ); };
    void ClearLog( int i ) { ClearLogInternal( i ); };
    wxArrayString ListAvailable();
    Logger* New( const wxString& name );
    bool FilenameRequired( const wxString& name );
    void Register( const wxString& name, InstantiatorBase* ins );
    void NotifyUpdate();
};

#endif
